import { _decorator, AudioClip, AudioSource, Button, Color, Component, EPhysics2DDrawFlags, Graphics, instantiate, Label, math, Node, NodePool, PhysicsSystem, PhysicsSystem2D, Prefab, Sprite, SpriteAtlas, Tween, tween, UIOpacity, UITransform, v3, Vec2, Vec3 } from 'cc';
import { Block } from './Block/Block';
import { TxDian } from './Effect/TxDian';
import { Hero } from './Hero/Hero';
import { Animation } from 'cc';
import { EffectManager } from './Effect/EffectManager';
import { AudioManager } from './Audio/AudioManager';
import { Utils } from './Utils';
import { HeroManager } from './Hero/HeroManager';
import { BlockManager } from './Block/BlockManager';
const { ccclass, property } = _decorator;

export enum GemeType {
    Ready = 0,
    Play = 1,
    Over = 2
}

@ccclass('Game')
export class Game extends Component {
    @property(Node) nodeHero: Node = null!;
    @property(Node) hero_2: Node = null!;

    @property(Sprite) bg: Sprite = null;
    @property(Node) nodeReady: Node = null;
    @property(Node) nodePlay: Node = null;
    @property(Node) nodePHB: Node = null;
    @property(Node) nodeOver: Node = null;
    @property(Node) nodeAudio: Node = null;
    @property(Node) itemParent: Node = null;
    @property(Prefab) pre_item: Prefab = null;
    @property(Label) tx_score: Label = null;
    @property(Node) tx_guangQuan: Node = null;  // 光圈

    @property(Node) nodeBlock: Node = null;
    @property(Prefab) pre_block: Prefab = null;
    @property(Graphics) graphics: Graphics = null

    @property(Button) btn_start: Button = null;
    @property(Node) nodeDian: Node = null;

    @property(Label)
    public lab_score = null;
    @property(Label)
    public lab_currScoreOver = null;
    @property(Label)
    public lab_bestScoreOver = null;
    @property(Node)
    public phOver = null;
    @property(SpriteAtlas)
    public spa_touXiang = null;


    @property(Prefab)
    public pre_dian = null;
    @property(AudioClip)
    public audio_score_1 = null;
    @property(AudioClip)
    public audio_score_2 = null;
    @property(AudioClip)
    public audio_fall = null;
    @property(AudioClip)
    public audio_touch_1 = null;
    @property(AudioClip)
    public audio_touch_2 = null;

    public static instance: Game;
    //public blockPool: NodePool;
    private callBackHeroJump: Function | null = null;
    private callBacktxDian: Function | null = null; // 创建星星
    private callBackGetScore: Function;
    //private dianPool: NodePool;
    private doubleScore: number = 1;

    private currScore: number = 0;  // 当前获得分数
    private timeTouch: number = 0;
    private isTouchBegin: boolean = false;
    private isTouchStart: boolean = false;
    public isDoubleScore: boolean = false;

    public lastBlock: Block = null;

    public isGetScore: number = -1;
    public isCollision: boolean = false;
    public gameType: GemeType = GemeType.Ready;
    private bolckDirection: Vec3 = Vec3.ZERO;
    public showNextBlock: boolean = true;     // 是否显示并创建下一个障碍物
    private blockIndex = -1;              // 当前障碍物索引
    private tweens: Map<Node, Tween<Node>> = new Map();


    arrColorBg = [
        { r: 191, g: 192, b: 201 },
        { r: 244, g: 220, b: 216 },
        { r: 198, g: 224, b: 211 },
        { r: 242, g: 215, b: 171 },
        { r: 165, g: 191, b: 216 },
        { r: 231, g: 219, b: 222 },
    ]
    arr_infor = [
        { name: '我', touXiang: 2, score: 1001 },
    ]


    onLoad() {
        PhysicsSystem2D.instance.enable = true;
        PhysicsSystem2D.instance.debugDrawFlags = EPhysics2DDrawFlags.All;
        Game.instance = this; // 确保静态属性 instance 指向当前 Game 实例
        (window as any).game = this;
        this.nodeReady.active = true;
        this.nodePlay.active = false;
        this.nodePHB.active = false;
        this.nodeOver.active = false;

        this.nodeReady.setSiblingIndex(9);
        this.nodeOver.setSiblingIndex(9);
        this.nodePHB.setSiblingIndex(10);

        this.gameType = GemeType.Ready;
        this.nodeHero.active = false;
        this.tx_score.node.getComponent(UIOpacity).opacity = 0;
        this.tx_guangQuan.getComponent(UIOpacity).opacity = 0;
        this.tx_guangQuan.setSiblingIndex(10);

        this.setReady();
        this.node.on(Node.EventType.TOUCH_START, this.touchStart, this);
        this.node.on(Node.EventType.TOUCH_END, this.touchEnd, this);
        this.node.on(Node.EventType.TOUCH_CANCEL, this.touchEnd, this);
        this.btn_start.node.on(Button.EventType.CLICK, this.startGame, this);
    }

    private startGame() {
        console.log('点击了开始按钮');

        this.unschedule(this.callBackHeroJump);
        this.doubleScore = 1;

        this.currScore = 0;
        this.lab_score.string = this.currScore;
        this.gameType = GemeType.Play;
        this.nodePlay.active = true;
        this.nodeReady.active = false;
        this.nodeHero.active = true;
        this.isTouchStart == false;

        // this.graphics.clear()
        Tween.stopAllByTarget(this.node);//停止所有
        //停止每个方块节点
        for (let i = this.nodeBlock.children.length - 1; i >= 0; i--) {
            this.stopTween(this.nodeBlock.children[i]);
        }

        this.initBlock();
    }

    // 停止指定节点的 tween
    stopTween(node: Node) {
        const t = this.tweens.get(node);
        if (t) {
            t.stop(); // 停止 tween
            this.tweens.delete(node); // 从 Map 中移除引用
        }
    }

    // 准备设置
    private setReady() {
        this.nodeHero.active = true;
        this.hero_2.active = false
        this.initBlock();
        this.callBackHeroJump = () => {
            this.herojunmReady();
        };
        this.schedule(this.callBackHeroJump, 3);
    }

    /** 初始化障碍物,同时计算好移动方向*/
    private initBlock() {
        HeroManager.instance.setHeroAct(new Vec3(-140, -140), this.nodeHero)
        BlockManager.instance.cleanAllblock(this.nodeBlock);
        const v1 = BlockManager.instance.createBlock(new Vec3(-140, -140), 0, 1, this.nodeBlock, this.pre_block).pos_dianWorldPos;
        const v2 = BlockManager.instance.createBlock(new Vec3(110, 32), 1, 2, this.nodeBlock, this.pre_block).pos_dianWorldPos;
        this.bolckDirection = v2.subtract(v1).normalize();
        this.blockIndex = 2;
    }

    /** 主角开始跳跃 */
    private herojunmReady() {
        const pos_blockEnd = BlockManager.instance.getLastBlockPos(this.nodeBlock);
        const pos_hero = this.nodeHero.position;

        const heroHeight = this.nodeHero.getComponent(UITransform).height / 2;
        // this.graphicsLine(pos_blockEnd, pos_hero);
        var pos_end = new Vec3(pos_blockEnd.x, pos_blockEnd.y + heroHeight);
        var direction = pos_blockEnd.subtract(pos_hero).normalize();

        var act_0 = HeroManager.instance.heroAct_0(this.nodeHero, pos_hero, heroHeight);
        var act_1 = HeroManager.instance.heroAct_1(this.nodeHero, pos_end);
        var act_2 = HeroManager.instance.heroAct_2(this.nodeHero,);
        var act_3 = HeroManager.instance.heroAct_3(this.nodeHero);
        var act_4 = HeroManager.instance.heroAct_4(this.nodeHero, pos_end, heroHeight);

        var act_over = () => {
            this.blockIndex++;
            BlockManager.instance.createNextBlock(this.nodeBlock, this.pre_block, this.bolckDirection, this.blockIndex);
            this.graphics.clear();
        }

        // 根据方向选择顺时针或逆时针旋转
        if (direction.x > 0) {
            var act_5 = tween().parallel(act_1, act_3);
            tween(this.node).call(act_0).then(act_5).call(act_4).call(act_over).start();
        } else {
            var act_6 = tween().parallel(act_1, act_2);
            tween(this.node).call(act_0).then(act_6).call(act_4).call(act_over).start();
        }
    }


    /** 绘制辅助线 */
    private graphicsLine(beginPos: Vec3, endPos: Vec3) {
        // 设置线条样式
        this.graphics.clear();
        this.graphics.lineWidth = 10;
        this.graphics.strokeColor = Color.RED;

        // 开始绘制路径
        this.graphics.moveTo(beginPos.x, beginPos.y);
        this.graphics.lineTo(endPos.x, endPos.y);

        // 完成绘制
        this.graphics.stroke();
    }


    //增加分数  
    public addScore(num: any) {
        if (this.callBackGetScore) {
            this.unschedule(this.callBackGetScore);
        }

        var addScore = num;
        if (num == 2) {
            this.doubleScore = this.doubleScore * 2
            addScore = this.doubleScore;
        } else if (num == 1) {
            this.doubleScore = 1;
        }
        AudioManager.instance.playAudio(this.audio_score_2, false, this.nodeAudio);

        if (num == 1 || num == 2) {
            if (Math.random() < 0.1) {
                EffectManager.instance.setRandomBgColor(this.bg, this.arrColorBg);
            }
            var numDian = 5 + Math.floor(Math.random() * 7);
            for (let i = 0; i < numDian; i++) {
                EffectManager.instance.createDian(this.nodeHero.position, 'end', this.nodeDian, this.pre_dian);
            }
        }
        // 播放上飘分数
        EffectManager.instance.scoreEffect(this.tx_score, addScore, this.nodeHero.position.x, this.nodeHero.position.y);
        this.currScore += addScore;
        this.lab_score.string = this.currScore;
        // 播放光圈特效
        if (num == 2) {
            EffectManager.instance.guangQuanEffect(this.tx_guangQuan, this.nodeHero.position.x, this.nodeHero.position.y)
        }
    }

    //判断得分方块类型
    private txBlock() {
        var children = this.node.children;
        var i_num = 0;
        for (let i = children.length - 1; i >= 0; i--) {
            var js = children[i].getComponent(Block);
            if (js) {
                i_num++
                if (i_num == 2 && js.blockType > 18) {
                    this.callBackGetScore = function () {
                        if (this.gameType != GemeType.Play) return
                        if (children[i].getComponent(Block).blockType == 19) {
                            this.addScore(5);
                        } else if (children[i].getComponent(Block).blockType == 20) {
                            this.addScore(8);
                        } else if (children[i].getComponent(Block).blockType == 21) {
                            this.addScore(10);
                        }
                        children[i].getComponent(Block).playAnima();
                    }
                    this.scheduleOnce(this.callBackGetScore, 3);
                }
            }
        }
    }

    /** 整体移动主角和障碍物 */
    public moveHeroWithBlocks() {
        this.nodeHero.getComponent(Hero).canTouch = false;
        var arr_pos = [];
        var children = this.nodeBlock.children;
        for (let i = children.length - 1; i >= 0; i--) {
            var js = children[i].getComponent(Block);
            js.canTouch = false;
            arr_pos.push(js.pos_dianWorldPos);
        }
        var pos_cha = new Vec3((arr_pos[0].x - arr_pos[1].x) / 2, (arr_pos[0].y - arr_pos[1].y) / 2);
        var pos_move = new Vec3(0 - (arr_pos[1].x + pos_cha.x), -150 - (arr_pos[1].y + pos_cha.y));
        for (let i = children.length - 1; i >= 0; i--) {
            const act_1 = { position: new Vec3(pos_move.x, pos_move.y, 0) };
            const moveChildren = tween(children[i]).by(0.5, act_1).call(() => { children[i].getComponent(Block).canTouch = true; }).start();
            this.tweens.set(children[i], moveChildren); // 将 tween 与对应的节点保存到 Map 中
        }
        const act_1 = { position: new Vec3(pos_move.x, pos_move.y, 0) };
        tween(this.nodeHero)
            .by(0.5, act_1)
            .call(() => {
                this.nodeHero.getComponent(Hero).canTouch = true;
            })
            .start();
        tween(this.tx_score.node)
            .by(0.5, act_1)
            .start();
        this.txBlock();
    }

    /** 检测是否可以继续触发 */
    private canTouch(): boolean {
        var children = this.nodeBlock.children;
        for (let i = children.length - 1; i >= 0; i--) {
            var js = children[i].getComponent(Block)
            if (js) {
                if (js.canTouch == false) {
                    return false
                }
            }
        }
        return true
    }

    private touchStart() {
        console.error(this.canTouch());
        if (!this.canTouch()) return;
        if (this.nodeHero.getComponent(Hero).canTouch == false) return;
        this.isTouchStart = true;
        this.timeTouch = 0;
        this.isTouchBegin = true;

        this.isCollision = false;
        this.nodeHero.eulerAngles = Vec3.ZERO;
        this.nodeHero.scale = Vec3.ONE;
        this.hero_2.active = false;
        AudioManager.instance.playAudio(this.audio_touch_1, true, this.nodeAudio);
        var numDian = 3 + Math.floor(Math.random() * 7);
        for (let i = 0; i < numDian; i++) {
            EffectManager.instance.createDian(this.nodeHero.position, 'start', this.nodeDian, this.pre_dian);
        }
        this.callBacktxDian = function () {
            var numDian = 3 + Math.floor(Math.random() * 7);
            for (let i = 0; i < numDian; i++) {
                EffectManager.instance.createDian(this.nodeHero.position, 'start', this.nodeDian, this.pre_dian);
            }
        }
        this.schedule(this.callBacktxDian, 0.5);
    }

    /** 开始计算按住持续时间 */
    protected update(dt: any) {
        if (this.isTouchBegin) {
            this.timeTouch++
            if (this.timeTouch >= 400) {
                this.timeTouch = 400
            }
            this.nodeBlock.children[this.nodeBlock.children.length - 2].getComponent(Block).onTouchBegin(dt);
            this.calHeroJumoPos();
        }
    }

    // 计算跳跃目标点 = 主角位置 + 跳跃方向*持续时间
    private calHeroJumoPos(): Vec3 {
        const pos_blockEnd = BlockManager.instance.getLastBlockPos(this.nodeBlock);
        const pos_hero = this.nodeHero.position.clone();
        const pos_end = pos_blockEnd.subtract(pos_hero).normalize().multiplyScalar(this.timeTouch * 4).add(pos_hero);
        this.graphicsLine(pos_hero, pos_end);
        return pos_end;
    }

    private touchEnd() {
        if (this.isTouchStart == false) return;
        if (!this.canTouch()) return;
        if (this.nodeHero.getComponent(Hero).canTouch == false) return;
        this.isTouchBegin = false;
        this.isTouchStart = false;
        AudioManager.instance.stopAudioOnce(this.audio_touch_1, this.nodeAudio);
        // 停止创建星星
        EffectManager.instance.cleanAllTXDian(this.nodeDian);
        this.unschedule(this.callBacktxDian);
        this.nodeBlock.children[this.nodeBlock.children.length - 2].getComponent(Block).onTouchEnd()
        const heroHeight = this.nodeHero.getComponent(UITransform).height / 2;
        const pos_hero = this.nodeHero.position;
        const pos_end = this.calHeroJumoPos().add(new Vec3(0, heroHeight));

        this.showNextBlock = false;

        this.nodeHero.getComponent(Hero).canTouch = false;

        var act_0 = HeroManager.instance.heroAct_0(this.nodeHero, pos_hero, heroHeight);
        var act_1 = HeroManager.instance.heroAct_1(this.nodeHero, pos_end);
        var act_2 = HeroManager.instance.heroAct_2(this.nodeHero,);
        var act_3 = HeroManager.instance.heroAct_3(this.nodeHero);
        var act_4 = HeroManager.instance.heroAct_4_touchEnd(this.nodeHero, this.hero_2, pos_end, heroHeight);

        var act_4_touchEnd = () => {
            this.scheduleOnce(() => {
                if (!this.isCollision) {
                    this.hero_2.active = false;
                    this.gameType = GemeType.Over;

                    const act_001 = HeroManager.instance.heroAct_touchEnd_over(this.nodeHero);
                    const act_002 = () => { this.gameOver(); };
                    new Tween(this.nodeHero)
                        .then(act_001)
                        .call(act_002)
                        .start();
                }
                if (this.isCollision && this.showNextBlock) {
                    if (this.isDoubleScore) {
                        this.addScore(2);
                    } else {
                        this.addScore(1);
                    }
                }
                this.hero_2.active = false;
                if (this.showNextBlock) {
                    this.nodeHero.getComponent(Hero).canTouch = false;
                    this.blockIndex++;
                    BlockManager.instance.createNextBlock(this.nodeBlock, this.pre_block, this.bolckDirection, this.blockIndex);
                }
            }, 0.1)
        };


        // 根据方向选择顺时针或逆时针旋转
        if ((pos_end.x - pos_hero.x) > 0) {
            var act_5 = tween().parallel(act_1, act_3);
            tween(this.node).call(act_0).then(act_5).call(act_4).call(act_4_touchEnd).start();
        } else {
            var act_6 = tween().parallel(act_1, act_2);
            tween(this.node).call(act_0).then(act_6).call(act_4).call(act_4_touchEnd).start();
        }
    }

    //游戏结束
    gameOver() {
        this.lastBlock = null;
        AudioManager.instance.playAudio(this.audio_fall, false, this.nodeAudio);
        this.lab_currScoreOver.string = this.currScore.toString();
        var bestScore = localStorage.getItem('bestScore');
        if (bestScore == null) {
            bestScore = this.currScore.toString();
            localStorage.setItem('bestScore', bestScore);
        } else {
            if (parseInt(bestScore) < this.currScore) {
                bestScore = this.currScore.toString();
                localStorage.setItem('bestScore', bestScore)
            }
        }
        this.lab_bestScoreOver.string = '历史最高分：' + bestScore
        this.nodeOver.active = true
        for (let i = 0; i < this.arr_infor.length; i++) {
            if (this.arr_infor[i].name == '我') {
                var bestScore = localStorage.getItem('bestScore');
                this.arr_infor[i].score = parseInt(bestScore);
            }
        }
        this.setPhOver()
    }

    compare(property: any) {
        return function (a, b) {
            var value1 = a[property];
            var value2 = b[property];
            return value2 - value1;
        }
    }


    setPhOver() {
        var i_mc_wo = 0
        this.arr_infor.sort(this.compare('score'))
        for (let i = 0; i < this.arr_infor.length; i++) {
            if (this.arr_infor[i].name == '我') {
                i_mc_wo = i + 1
                var bestScore = localStorage.getItem('bestScore')
                this.phOver.getChildByName('node_1').getChildByName('label_mingci').getComponent(Label).string = i_mc_wo
                this.phOver.getChildByName('node_1').getChildByName('label_score').getComponent(Label).string = bestScore
                break
            }
        }
    }

    clickBtn(sender: any, str: any) {
        if (str == 'phb') {
            console.log('点击了排行榜按钮');
            this.nodePHB.active = true;
        } else if (str == 'closePhb') {
            console.log('点击了排行榜关闭按钮');
            this.nodePHB.active = false;
        } else if (str == 'btnRePlay') {//再玩一次 
            this.doubleScore = 1;
            this.nodeOver.active = false;
            this.currScore = 0;
            this.lab_score.string = this.currScore;
            this.gameType = GemeType.Play;
            this.initBlock();
        } else if (str == 'btnphbOver') {//排行榜（over） 
            this.nodePHB.active = true;
        }
    }
}
